<template>
  <video
    v-if="Boolean(video.src)"
    crossorigin="anonymous"
    hidden
    ref="videoElem"
    preload="auto"
    controls
    muted
    :src="video.src"
    @loadeddata="handleLoadeddata"
    @seeked="handleSeeked"
    @error="handleError"
  >
    Sorry, your browser doesn't support embedded videos.
  </video>
</template>

<script setup>
import { inject, nextTick } from 'vue'

import * as utils from 'video-action/libs/utils.js'
import { message } from 'ant-design-vue';

const video = inject('video');
const annotationState = inject('annotationState');
const preferenceState = inject('preferenceState');

const handleLoadeddata = (event) => {
  // utils.notify('Video loaded successfully!', 'positive')
  video.value.duration = event.target.duration;
  video.value.width = event.target.videoWidth;
  video.value.height = event.target.videoHeight;
  video.value.frames = Math.round(video.value.fps * video.value.duration);

  const keyframeList = [];
  // 若无关键帧列表则初始化
  if (0 == annotationState.value.keyframeList.length) {
    for (let i = 0; i < video.value.frames; i += preferenceState.value.defaultFpk) {
      keyframeList.push(i)
    }
    annotationState.value.keyframeList = keyframeList
  }
  const interval = parseFloat((1 / video.value.fps).toFixed(3))
  // add keyframe to priorityQueue
  for (const keyframe of keyframeList) {
    if (keyframe !== 0) {
      annotationState.value.priorityQueue.push(keyframe)
    }
  }
  // add frame index into the backendQueue
  // 1. every one second
  annotationState.value.backendQueue = []
  for (let i = 1.0; i < video.value.duration; i++) {
    const index = utils.time2index(video.value.fps, i)
    if (keyframeList.indexOf(index) === -1) {
      annotationState.value.backendQueue.push(index)
    }
  }
  // 2. every 1 / fps second
  annotationState.value.priorityQueue = []
  for (let i = interval; i < video.value.duration; i += interval) {
    if (i.toFixed(1) % 1 !== 0) {
      annotationState.value.backendQueue.push(utils.time2index(video.value.fps, i))
    }
  }
  annotationState.value.cachedFrameList = []
  nextTick(() => {
    event.target.currentTime = 0.0
  })
}

let canvas
let ctx
const handleSeeked = (event) => {
  if (video.value.src) {
    const videoElement = event.target
    const currentTime = videoElement.currentTime
    const currentIndex = utils.time2index(video.value.fps, currentTime)
    if (!annotationState.value.cachedFrameList[currentIndex]) {
      annotationState.value.isCaching = true
      // get the image
      if (!ctx) {
        canvas = document.createElement('canvas')
        canvas.width = video.value.width
        canvas.height = video.value.height
        ctx = canvas.getContext('2d')
      } else {
        ctx.clearRect(0, 0, canvas.width, canvas.height)
      }
      ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height)
      // save to cachedFrames
      canvas.toBlob((blob) => {
        annotationState.value.cachedFrameList[currentIndex] = blob
      }, 'image/jpeg')
    }
    // trigger next frame
    if (!annotationState.value.cachedFrameList[annotationState.value.frame.left]) {
      videoElement.currentTime = utils.index2time(video.value.fps, annotationState.value.frame.left)
    } else if (!annotationState.value.cachedFrameList[annotationState.value.frame.right]) {
      videoElement.currentTime = utils.index2time(video.value.fps, annotationState.value.frame.right)
    } else if (annotationState.value.priorityQueue.length !== 0) {
      videoElement.currentTime = utils.index2time(video.value.fps, annotationState.value.priorityQueue.shift())
    } else if (annotationState.value.backendQueue.length !== 0) {
      videoElement.currentTime = utils.index2time(video.value.fps, annotationState.value.backendQueue.shift())
    } else {
      annotationState.value.isCaching = false
    }
  }
}

const handleError = (event) => {
  console.error(event)
  message.error(`Could not load video: ${video.value.src}: ${event.target.error.message}`, 'negative')
  // annotationState.value.reset()
}
</script>
